using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Reflection;

namespace Crumbs
{
	class DbgInfoFilter : Stream
	{
		private Stream m_wrapped;
		private readonly List<RequestDebugInfo> m_infos;
		private long m_pos;
    static string s_css;

    static DbgInfoFilter()
    {
      using(Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("Crumbs.crumbs.css"))
      using (StreamReader reader = new StreamReader(stream))
      {
        string css = reader.ReadToEnd();               
        s_css = "<STYLE TYPE='text/css'>" + css + "</STYLE></head>";
      }
    }

		public DbgInfoFilter(Stream wrapped, List<RequestDebugInfo> infos)
		{
			m_wrapped = wrapped;
			m_infos = infos;
		}

		public override void Flush()
		{
			m_wrapped.Flush();
		}

		public override long Seek(long offset, SeekOrigin origin)
		{
			return m_wrapped.Seek(offset, origin);
		}

		public override void SetLength(long value)
		{
			m_wrapped.SetLength(value);
		}

		public override int Read(byte[] buffer, int offset, int count)
		{
			return m_wrapped.Read(buffer, offset, count);
		}

		public override void Write(byte[] buffer, int offset, int count)
		{
			byte[] data = new byte[count];
			Buffer.BlockCopy(buffer, offset, data, 0, count);
			string html = System.Text.Encoding.Default.GetString(buffer);

      html = html.Replace("</head>", GetCss());
      html = html.Replace("<body>", GetDebugInfo());

			byte[] outdata = System.Text.Encoding.Default.GetBytes(html);
			m_wrapped.Write(outdata, 0, outdata.GetLength(0));
		}

		public override bool CanRead
		{
			get { return true; }
		}

		public override bool CanSeek
		{
			get { return true; }
		}

		public override bool CanWrite
		{
			get { return true; }
		}

		public override long Length
		{
			get { return 0; }
		}

		public override long Position
		{
			get { return m_pos;}
			set { m_pos = value; }
		}

    private string GetCss()
    {
      return s_css;
    }

		private string GetDebugInfo()
		{
			StringBuilder sb = new StringBuilder();
			sb.Append(@"<body><script type='text/javascript'>
			jQuery(document).ready(function(){ jQuery('.debug_details').hide(); jQuery('#dbgwindow input').show();  });
			function closeDebugWnd(){ var options = {};	jQuery('#dbgwindow').slideToggle(150); };
			function toggleDebugDetails(){ var options = {};	jQuery('.debug_details').slideToggle(250); };
			</script><div id='dbgwindow'>
			<input type='button' value='close' onclick='closeDebugWnd();' />
			<input type='button' value='toggle details' onclick='toggleDebugDetails();' />    <h4>Debug Info</h4>");

			if (m_infos.Count < 1)
				sb.Append("No debug information.");
			else
			{
				foreach (RequestDebugInfo info in m_infos)
				{
					sb.AppendFormat("<p class='debug_summary'>{0} - {1} ms - SQL: {2}</p><div class='debug_details'><ul>", 
						info.Url, info.Duration, info.Summary);

					foreach (DebugInfoDetail detail in info.Details)
					{
						sb.AppendFormat("<li><div class='debug_timestamp'>{0} @ {1}</div>{2}</li>",
							detail.Scope, detail.Timestamp, detail.Description);
					}

					sb.Append("</ul></div>");
				}
			}
			sb.Append("</div>");


			return sb.ToString(	);
		}
	}
}